package com.ljf.authority.domain.validator;

import com.ljf.authority.domain.repository.AuthorityBaseApiTabulationRepository;
import com.ljf.authority.domain.repository.AuthorityBaseMenuTabulationRepository;
import com.ljf.authority.dto.command.AuthorityBaseApiTabulationActivationCommand;
import com.ljf.authority.dto.command.AuthorityBaseApiTabulationCommand;
import com.ljf.authority.dto.command.AuthorityBaseApiTabulationMenuCommand;
import com.ljf.authority.dto.command.AuthorityBaseApiTabulationTemplateCommand;
import com.ljf.authority.dto.query.AuthorityBaseApiTabulationQuery;
import com.ljf.authority.dto.query.AuthorityBaseMenuTabulationQuery;
import com.ljf.authority.enums.AuthorityBaseApiTabulationMethodEnum;
import com.ljf.authority.enums.AuthorityBaseApiTabulationPermissionTypeEnum;
import com.ljf.authority.enums.AuthorityBaseApiTabulationSynchronizationTypeEnum;
import com.ljf.authority.model.AuthorityBaseApiTabulation;
import com.ljf.authority.utils.CodeGenerateUtil;
import com.ljf.authority.vo.AuthorityBaseApiTabulationVO;
import com.ljf.common.domain.validator.BasisValidator;
import com.ljf.common.exception.ServiceException;
import com.ljf.common.utils.CollectionUtil;
import com.ljf.common.utils.EnumUtil;
import com.ljf.common.utils.StringUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;

/**
 * API列表定义  业务校验
 *
 * @author LJF
 * @since 2024-10-25
 */
@Component
@AllArgsConstructor
public class AuthorityBaseApiTabulationValidator extends BasisValidator<AuthorityBaseApiTabulationQuery, AuthorityBaseApiTabulationCommand, AuthorityBaseApiTabulationVO, AuthorityBaseApiTabulation, AuthorityBaseApiTabulationRepository> {

    private final AuthorityBaseMenuTabulationRepository menuTabulationRepository;

    @Override
    public void checkAdd(AuthorityBaseApiTabulationCommand command) throws ServiceException {
        super.checkAdd(command);
        this.checkChange(command);
    }

    /**
     * 通过模板批量新增API列表定义 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkAddBatchByTemplate(AuthorityBaseApiTabulationTemplateCommand command) throws ServiceException {
        if (CollectionUtil.isEmpty(command.getBackendList())) {
            throw new ServiceException("校验异常: 请选择生成模板");
        }
        String url = CodeGenerateUtil.convertToUrl(command.getTableName());
        List<String> codeList = CodeGenerateUtil.generateApiTabulationCode(url);
        for (String backend : command.getBackendList()) {
            if (!codeList.contains(backend)) {
                throw new ServiceException("校验异常: 模板异常");
            }
        }
        int count = repository.count(AuthorityBaseApiTabulationQuery.builder().codeList(command.getBackendList()).build());
        if (count > 0) {
            throw new ServiceException("校验异常: 后端已存在, 请刷新后重试");
        }
    }

    @Override
    public void checkEdit(AuthorityBaseApiTabulationCommand command) throws ServiceException {
        super.checkEdit(command);
        this.checkChange(command);
    }

    /**
     * 修改API列表定义激活状态 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditActivation(AuthorityBaseApiTabulationActivationCommand command) throws ServiceException {
        super.checkEditActivation(command.getIds(), command.getActivation());
    }

    /**
     * 修改API列表定义关联菜单 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditMenu(AuthorityBaseApiTabulationMenuCommand command) throws ServiceException {
        if (repository.countById(command.getId()) == 0) {
            throw new ServiceException("校验异常: 数据不存在, 请刷新后重试");
        }
        if (CollectionUtil.isNotEmpty(command.getMenuList())) {
            int count = menuTabulationRepository.count(
                    AuthorityBaseMenuTabulationQuery.builder()
                            .codeList(command.getMenuList())
                            .build()
            );
            if (count != command.getMenuList().size()) {
                throw new ServiceException("校验异常: 前端编码不存在");
            }
        }
    }

    /**
     * 查询API列表表单信息 业务校验
     *
     * @param url
     * @param method
     * @throws ServiceException
     */
    public void checkQueryInfo(String url, Integer method) throws ServiceException {
        if (StringUtil.isEmpty(url)) {
            throw new ServiceException("校验异常: URL不能为空");
        }
        if (method == null) {
            throw new ServiceException("校验异常: 方法不能为空");
        }
        if (!EnumUtil.checkCode(method, AuthorityBaseApiTabulationMethodEnum.values())) {
            throw new ServiceException("校验异常: 请求方法不存在");
        }
    }

    /**
     * 查询API列表模板 业务校验
     *
     * @param tableName
     * @throws ServiceException
     */
    public void checkQueryTemplate(String tableName) throws ServiceException {
        if (StringUtil.isEmpty(tableName)) {
            throw new ServiceException("校验异常: 表名不能为空");
        }
    }

    /**
     * 根据ID查询API列表关联菜单 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQueryMenuById(Long id) throws ServiceException {
        super.checkIdExist(id);
    }

    /**
     *
     *
     * @param command
     * @throws ServiceException
     */
    private void checkChange(AuthorityBaseApiTabulationCommand command) throws ServiceException {
        AuthorityBaseApiTabulationMethodEnum methodEnum = EnumUtil.getEnumByCode(command.getMethod(), AuthorityBaseApiTabulationMethodEnum.values());
        if (methodEnum == null) {
            throw new ServiceException("校验异常: 请求方法不存在");
        }
        if (!EnumUtil.checkCode(command.getPermissionType(), AuthorityBaseApiTabulationPermissionTypeEnum.values())) {
            throw new ServiceException("校验异常: 权限类型不存在");
        }
        if (!EnumUtil.checkCode(command.getSynchronizationType(), AuthorityBaseApiTabulationSynchronizationTypeEnum.values())) {
            throw new ServiceException("校验异常: 同步类型不存在");
        }
        String code = CodeGenerateUtil.generateApiTabulationCode(command.getUrl(), methodEnum.getCodeSign());
        if (command.getId() != null) {
            super.checkIdExist(command.getId());
        }
        List<AuthorityBaseApiTabulationVO> modelList = repository.selectList(
                AuthorityBaseApiTabulationQuery.builder().code(code).build()
        );
        if (CollectionUtil.isNotEmpty(modelList)) {
            if (command.getId() == null) {
                throw new ServiceException("校验异常: 后端已存在");
            }
            if (!Objects.equals(modelList.get(0).getId(), command.getId())) {
                throw new ServiceException("校验异常: 后端已存在");
            }
        }
    }

}
